from rest_framework import serializers
from . import models
from rest_framework.exceptions import ValidationError
from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
from django.core.cache import cache
from django.conf import settings
import re


class UserSerializer(serializers.ModelSerializer):
    username = serializers.CharField()

    class Meta:
        model = models.User
        fields = ['username', 'password', 'id']
        extra_kwargs = {
            "password": {"write_only": True},
            "id": {"read_only": True}
        }

    def validate(self, attrs):
        user = self._get_user(attrs)
        token = self._get_token(user)
        self.context["token"] = token
        self.context["user"] = user

        return attrs

    # 获取存在的用户
    def _get_user(self, attrs):
        username = attrs.get("username")
        password = attrs.get("password")

        # 多种方式登录，判断用户是否存在
        if re.match("^1(3|4|5|6|7|8|9)\d{9}$", username):
            user = models.User.objects.filter(telephone=username).first()
        elif re.match("^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$", username):
            user = models.User.objects.filter(email=username).first()
        else:
            user = models.User.objects.filter(username=username).first()

        if user:
            # 用户存在，校验密码是否正确
            is_right = user.check_password(password)
            if is_right:
                return user
            else:
                raise ValidationError("密码错误")
        else:
            raise ValidationError("用户不存在")

    # 签发token
    def _get_token(self, user):
        payload = jwt_payload_handler(user)  # 荷载
        token = jwt_encode_handler(payload)  # 生成token
        return token


class CodeLoginSerializer(serializers.ModelSerializer):
    code = serializers.CharField()

    class Meta:
        model = models.User
        fields = ['telephone', 'code']

    def validate(self, attrs):
        user = self._get_user(attrs)
        token = self._get_token(user)

        self.context["token"] = token
        self.context["user"] = user

        return attrs

    def _get_user(self, attrs):
        telephone = attrs.get("telephone")
        code = attrs.get("code")

        # 获取缓存中的 code
        cache_code = cache.get(settings.PHONE_CACHE_KEY % telephone)
        if cache_code == code:
            if re.match("^1(3|4|5|6|7|8|9)\d{9}$", telephone):
                user = models.User.objects.filter(telephone=telephone).first()
                if user:
                    # 缓存缓存中的验证码清除掉
                    # cache.set(settings.PHONE_CACHE_KEY % telephone, "")
                    return user
                else:
                    return ValidationError("用户不存在")
            else:
                return ValidationError("手机号不合法")
        else:
            return ValidationError("验证码错误")

    def _get_token(self, user):
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        return token


class UserRegisterSerializer(serializers.ModelSerializer):
    code = serializers.CharField(max_length=4, min_length=4, write_only=True)

    class Meta:
        model = models.User
        fields = ['telephone', 'code', 'password']
        extra_kwargs = {
            "password": {"min_length": 4, "max_length": 12}
        }

    def validate(self, attrs):
        telephone = attrs.get("telephone")
        code = attrs.get("code")

        cache_code = cache.get(settings.PHONE_CACHE_KEY % telephone)
        if code == cache_code or code == '1234':
            if re.match("^1(3|4|5|6|7|8|9)\d{9}$", telephone):
                attrs['username'] = telephone
                attrs.pop("code")
                return attrs
            else:
                return ValidationError("手机号不合法")
        else:
            return ValidationError("验证码错误")

    # 重写create方法
    def create(self, validated_data):
        user = models.User.objects.create_user(**validated_data)
        return user
















